/*
 * [y] hybris Platform
 *
 * Copyright (c) 2000-2017 SAP SE
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of SAP
 * Hybris ("Confidential Information"). You shall not disclose such
 * Confidential Information and shall use it only in accordance with the
 * terms of the license agreement you entered into with SAP Hybris.
 */
package de.hybris.y2ysync.task.runner.internal;

import de.hybris.platform.core.PK;
import de.hybris.platform.impex.jalo.ImpExMedia;
import de.hybris.platform.impex.jalo.exp.Export;
import de.hybris.platform.impex.jalo.exp.converter.DefaultExportResultHandler;
import de.hybris.platform.impex.model.ImpExMediaModel;
import de.hybris.platform.jalo.JaloBusinessException;
import de.hybris.platform.servicelayer.impex.ExportConfig;
import de.hybris.platform.servicelayer.impex.ExportResult;
import de.hybris.platform.servicelayer.impex.ExportService;
import de.hybris.platform.servicelayer.impex.impl.StreamBasedImpExResource;
import de.hybris.platform.servicelayer.model.ModelService;
import de.hybris.platform.servicelayer.user.UserService;

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.zip.ZipEntry;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.google.common.collect.ImmutableList;


/**
 *
 */
public class DemoImportScriptCreator
{
	private final static Logger LOG = Logger.getLogger(DemoImportScriptCreator.class);

	private final ModelService modelService;
	private final ExportService exportService;
	private final ExportScriptCreator exportScriptCreator;
	private final UserService userService;

	public DemoImportScriptCreator(final ModelService modelService, final ExportService exportService,
			final ExportScriptCreator exportScriptCreator, final UserService userService)
	{
		Objects.requireNonNull(modelService, "modelService can't be null");
		Objects.requireNonNull(exportService, "exportService can't be null");
		Objects.requireNonNull(exportScriptCreator, "exportScriptCreator can't be null");
		Objects.requireNonNull(userService, "userService can't be null");
		this.modelService = modelService;
		this.exportService = exportService;
		this.exportScriptCreator = exportScriptCreator;
		this.userService = userService;
	}

	public Collection<ImportScript> createImportScripts()
	{
		final String exportScript = this.exportScriptCreator.createInsertUpdateExportScript();
		LOG.info("exportScript:" + exportScript);
		final ExportConfig config = new ExportConfig();
		config.setValidationMode(ExportConfig.ValidationMode.STRICT);
		config.setEncoding("UTF-8");
		config.setScript(new StreamBasedImpExResource(IOUtils.toInputStream(exportScript), "UTF-8"));
		config.setSessionUser(this.userService.getAdminUser());

		final ExportResult exportResult = this.exportService.exportData(config);

		if (exportResult.isError() || !exportResult.isSuccessful())
		{
			throw new RuntimeException("Export has failed.");
		}
		try
		{
			final ImmutableList.Builder<ImportScript> resultBuilder = this.extractImportScripts(exportResult);
			this.addDeleteScriptIfNeeded(resultBuilder);
			return resultBuilder.build();
		}
		catch (JaloBusinessException | IOException e)
		{
			throw new RuntimeException("Export has failed.", e);
		}
	}

	private void addDeleteScriptIfNeeded(final ImmutableList.Builder<ImportScript> resultBuilder)
	{
		final String deleteCsv = this.exportScriptCreator.createDeleteCsv();
		if (StringUtils.isNotBlank(deleteCsv))
		{
			resultBuilder.add(new ImportScript(this.exportScriptCreator.getTypeCode(), this.exportScriptCreator.getRemoveHeader(),
					deleteCsv, null));
		}
	}

	private ImmutableList.Builder<ImportScript> extractImportScripts(final ExportResult exportResult)
			throws IOException, JaloBusinessException
	{
		final ImmutableList.Builder resultBuilder = ImmutableList.builder();
		final DefaultExportResultHandler handler = new DefaultExportResultHandler();
		handler.setExport((Export) this.modelService.getSource((Object) exportResult.getExport()));
		final List<ZipEntry> entries = handler
				.getZipEntries((ImpExMedia) this.modelService.getSource((Object) exportResult.getExportedData()));
		for (final ZipEntry entry : entries)
		{
			if (!entry.getName().equalsIgnoreCase(this.exportScriptCreator.getFileNameForInsertedOrUpdatedItems()))
			{
				continue;
			}

			final String dataContent = handler.getDataContent(entry).toString();
			resultBuilder.add(new ImportScript(this.exportScriptCreator.getTypeCode(),
					this.exportScriptCreator.getInsertUpdateHeader(), dataContent, this.getMediaArchivePk(exportResult)));
		}

		return resultBuilder;
	}

	private PK getMediaArchivePk(final ExportResult exportResult)
	{
		final ImpExMediaModel exportedMedia = exportResult.getExportedMedia();
		if (exportedMedia != null)
		{
			LOG.info("media code:" + exportedMedia.getCode());
			LOG.info("media pk:" + exportedMedia.getPk());
		}
		return exportedMedia != null ? exportedMedia.getPk() : null;
	}
}
